home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Skunkware 98
/
Skunkware 98.iso
/
src
/
interp
/
tclStruct1.2.tar.gz
/
tclStruct1.2.tar
/
tclStruct1.2
/
stRead.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-10-17
|
9KB
|
323 lines
/*
* tclStruct package
* Support 'C' structures in Tcl
*
* Written by Matthew Costello
* (c) 1995 AT&T Global Information Solutions, Dayton Ohio USA
*
* See the file "license.terms" for information on usage and
* redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "stInternal.h"
STRUCT_SCCSID("@(#)tclStruct:stRead.c 1.3 95/10/17")
#define STRUCT_READ_UNBUFFERED 0001
#define STRUCT_READ_EOFOK 0002
#define STRUCT_READ_MOD4 0004
#define STRUCT_READ_PARTIAL 0010
#define STRUCT_READ_ERROR 0100
#define STRUCT_READ_EOF 0200
/*
* Parse the two arguments:
* object [objlen]
* for all the functions that send or receive structure objects.
* object The name of the object, or a pointer to one.
* objlen (optional) Either a number, or the name of a variable
*/
int
Struct_ParseObjectBuffer( interp, argc, argv, message, length, result )
Tcl_Interp *interp;
int argc; /* I */
char **argv; /* I */
char **message; /* O - location of message buffer */
int *length; /* O - length of message buffer */
char **result; /* O - name of variable to store received length in */
{
Struct_Object object;
if (argc < 1 || argc > 2) {
Tcl_AppendResult(interp,
"invalid number of arguments to Struct_ParseObjectBuffer",
(char *)NULL );
return TCL_ERROR;
}
/* If the 'result' is non-null, then we return the name of the
* variable to store the resultant object length (on a receive).
*/
if (result != NULL)
*result = NULL;
/* Get the object.
*/
if (Struct_GetObject( interp, argv[0], &object) != TCL_OK) {
return TCL_ERROR;
}
*message = object.data;
*length = object.size; /* Size of object */
/* If an explicit message length is specified, it can either be a
* number, or the name of a variable which contains a number.
* If no explicit length is specified then we use the
* size of the message buffer.
*/
if (argc > 1) {
char *value;
int message_length;
if ((value = Tcl_GetVar(interp, argv[1], 0)) == NULL) {
/* Not a var, must be an integet value */
value = argv[1];
} else if (result != NULL) {
/* A variable was specified. */
*result = argv[1];
}
if (Tcl_GetInt( interp, value, &message_length ) == TCL_ERROR) {
Struct_ReleaseType(object.type);
return TCL_ERROR;
}
#ifdef DEBUG
if ((message_length > object.size) &&
!(object.type->flags & STRUCT_FLAG_VARLEN)) {
Tcl_AppendResult(interp,"length \"", argv[1],
"\" is longer than object \"", value, "\"",NULL);
Struct_ReleaseType(object.type);
return TCL_ERROR;
}
#endif
*length = message_length;
}
/* Free up the object type now that we no longer have need of it.
*/
Struct_ReleaseType(object.type);
return TCL_OK;
}
/*
* struct_read read binary data
* struct_read file object ?objlen?
*/
int
Struct_ReadCmd(cdata, interp, argc, argv)
ClientData cdata; /* Client Data */
Tcl_Interp *interp; /* Current interpreter. */
int argc; /* Number of arguments. */
char **argv; /* Argument strings. */
{
FILE *f;
int bytesRead;
int totalRead = 0;
char *buffer;
int length;
char *result;
int flags = 0;
Struct_PkgInfo(cdata,si_cmdCount) += 1;
#ifdef DEBUG
if (struct_debug & (DBG_COMMAND)) Struct_PrintCommand(argc,argv);
#endif
for ( length = 1; length < argc && argv[length][0] == '-'; length++ ) {
if (strcmp(argv[length],"-eofok") == 0)
flags |= STRUCT_READ_EOFOK;
else if (strcmp(argv[length],"-unbuffered") == 0)
flags |= STRUCT_READ_UNBUFFERED;
else if (strcmp(argv[length],"-partial") == 0)
flags |= STRUCT_READ_PARTIAL;
else if (strcmp(argv[length],"-mod4") == 0)
flags |= STRUCT_READ_MOD4;
else {
Tcl_AppendResult(interp, "invalid flag to ", argv[0],
": flags are -eofok, -unbuffered, and -partial",
(char *)NULL );
return TCL_ERROR;
}
}
if (argc < length+2 || argc > length+3) {
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" ?-eofok? ?-unbuffered? ?-partial? fileId object ?objlen?\"", (char *) NULL);
return TCL_ERROR;
}
argc -= length;
argv += length;
if (Tcl_GetOpenFile(interp, argv[0], 0, 1, &f) != TCL_OK) {
return TCL_ERROR;
}
if (Struct_ParseObjectBuffer( interp, argc-1, argv+1, &buffer, &length, &result ) == TCL_ERROR)
return TCL_ERROR;
if (flags & STRUCT_READ_MOD4)
length = (length + 3) & ~03;
/* Continue reading from the file until we have what we
* need. This loop is written this way so a read of '0'
* will succeed without returning a false EOF.
*/
while (length > 0) {
if (flags & STRUCT_READ_UNBUFFERED) {
/* Unbuffered - raw read */
bytesRead = read(fileno(f), buffer, length);
if (bytesRead < 0)
flags |= STRUCT_READ_ERROR;
if (bytesRead == 0)
flags |= STRUCT_READ_EOF;
} else {
/* Buffered read */
clearerr(f);
bytesRead = fread(buffer, 1, length, f);
if (ferror(f))
flags |= STRUCT_READ_ERROR;
if (feof(f))
flags |= STRUCT_READ_EOF;
}
/* Handle errors reading from the file.
*/
if (flags & STRUCT_READ_ERROR) { /* ERROR reading */
Tcl_AppendResult(interp, "error reading \"", argv[0],
"\": ", Tcl_PosixError(interp), (char *) NULL);
return TCL_ERROR;
}
if (flags & STRUCT_READ_EOF && !(flags & STRUCT_READ_EOFOK)) {
Tcl_AppendResult(interp, "unexpected EOF on \"", argv[0],
"\"", (char *) NULL);
return TCL_ERROR;
}
/* How many have we read.
*/
totalRead += bytesRead;
#ifdef DEBUG
if ((bytesRead != length) && (struct_debug & (DBG_IO)))
printf("Partial read of %d bytes (wanted %d, total %d)\n",
bytesRead, length, totalRead );
#endif
/* Update the count of the number of bytes that we
* need to read.
*/
buffer += bytesRead;
length -= bytesRead;
/* If partial reads are okay, then we can break out of our
* read loop immediately.
*/
if (flags & STRUCT_READ_PARTIAL)
break;
if ((flags & STRUCT_READ_EOF) && (length != 0)) {
Tcl_AppendResult(interp, "unexpected EOF on \"", argv[0],
"\" resulted in a partial read", (char *) NULL);
return TCL_ERROR;
}
}
/* Return the number of bytes read */
sprintf( interp->result, "%d", totalRead );
if (result != NULL)
Tcl_SetVar( interp, result, interp->result, 0 );
return TCL_OK;
}
/*
* struct_write write binary data
* struct_write file object ?objlen?
*/
int
Struct_WriteCmd(cdata, interp, argc, argv)
ClientData cdata; /* Client Data */
Tcl_Interp *interp; /* Current interpreter. */
int argc; /* Number of arguments. */
char **argv; /* Argument strings. */
{
FILE *f;
int bytesWritten;
int totalWritten = 0;
char *buffer;
int length;
char *result;
int flags = 0;
Struct_PkgInfo(cdata,si_cmdCount) += 1;
#ifdef DEBUG
if (struct_debug & (DBG_COMMAND)) Struct_PrintCommand(argc,argv);
#endif
for ( length = 1; length < argc && argv[length][0] == '-'; length++ ) {
if (strcmp(argv[length],"-unbuffered") == 0)
flags |= STRUCT_READ_UNBUFFERED;
else if (strcmp(argv[length],"-partial") == 0)
flags |= STRUCT_READ_PARTIAL;
else if (strcmp(argv[length],"-mod4") == 0)
flags |= STRUCT_READ_MOD4;
else {
Tcl_AppendResult(interp, "invalid flag to ", argv[0],
": flags are -eofok, -unbuffered, and -partial",
(char *)NULL );
return TCL_ERROR;
}
}
if (argc < length+2 || argc > length+3) {
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" fileId object ?objlen?\"", (char *) NULL);
return TCL_ERROR;
}
argc -= length;
argv += length;
if (Tcl_GetOpenFile(interp, argv[0], 1, 1, &f) != TCL_OK) {
return TCL_ERROR;
}
if (Struct_ParseObjectBuffer( interp, argc-1, argv+1, &buffer, &length, &result ) == TCL_ERROR)
return TCL_ERROR;
if (flags & STRUCT_READ_MOD4)
length = (length + 3) & ~03;
/* Continue writing from the file until we have written
* everything. This loop is written this way so a write
* of '0' will not do anything.
*/
while (length > 0) {
if (flags & STRUCT_READ_UNBUFFERED) {
/* Unbuffered - raw write */
bytesWritten = write(fileno(f), buffer, length);
if (bytesWritten < 0)
flags |= STRUCT_READ_ERROR;
} else {
/* Buffered write */
clearerr(f);
bytesWritten = fwrite(buffer, 1, length, f);
if (ferror(f))
flags |= STRUCT_READ_ERROR;
}
/* Handle errors */
if (flags & STRUCT_READ_ERROR) { /* ERROR writeing */
Tcl_AppendResult(interp, "error writing \"", argv[0],
"\": ", Tcl_PosixError(interp), (char *) NULL);
return TCL_ERROR;
}
/* How many have we written so far. */
totalWritten += bytesWritten;
#ifdef DEBUG
if ((bytesWritten != length) && (struct_debug & (DBG_IO)))
printf("Partial write of %d bytes (wanted %d, total %d)\n",
bytesWritten, length, totalWritten );
#endif
if (flags & STRUCT_READ_PARTIAL)
break;
buffer += bytesWritten;
length -= bytesWritten;
}
/* Return the number of bytes written */
sprintf( interp->result, "%d", totalWritten );
if (result != NULL)
Tcl_SetVar( interp, result, interp->result, 0 );
return TCL_OK;
}